﻿using System;
using System.Linq;
using RayDen.Library.Core;
using RayDen.Library.Core.Primitives;

namespace RayDen.RayEngine.Core.Types
{
    public struct GpuSmitsBVHNode : ISerializableValue
    {
        public const int NodeSize = 32;
        public AABBInfo bbox;
        public uint primitive;
        public uint skipIndex;

        public override string ToString()
        {
            return string.Format("SkipIndex {0}, PrimitiveIndex {1} BBox {2}", skipIndex, primitive, bbox );
        }

        public byte[] GetData()
        {
            var chunks = new[]
                {
                    Int32Single.Create(bbox.Min.x),
                    Int32Single.Create(bbox.Min.y),
                    Int32Single.Create(bbox.Min.z),
                    Int32Single.Create(bbox.Max.x),
                    Int32Single.Create(bbox.Max.y),
                    Int32Single.Create(bbox.Max.z),
                    Int32Single.Create(primitive),
                    Int32Single.Create(skipIndex)
                };
            return chunks.SelectMany(item => item.GetBytes()).ToArray();
        }
        public GpuSmitsBVHNode(byte[] chunk)
        {
            var chunks = new[]
                {
                    Int32Single.Create(chunk), //0,1,2,3
                    Int32Single.Create(chunk, 4),
                    Int32Single.Create(chunk, 8),
                    Int32Single.Create(chunk, 12),
                    Int32Single.Create(chunk, 16),
                    Int32Single.Create(chunk, 20),
                    Int32Single.Create(chunk, 24),
                    Int32Single.Create(chunk, 28)
                };
            var chunks2 = new[]
                {
                    Int32Single.Create(chunk), //0,1,2,3
                    Int32Single.Create(chunk, 4),
                    Int32Single.Create(chunk, 8),
                    Int32Single.Create(chunk, 12),
                    Int32Single.Create(chunk, 16),
                    Int32Single.Create(chunk, 20),
                    Int32Single.Create(chunk, 24),
                    Int32Single.Create(chunk, 28)
                };
            bbox = new AABBInfo(new Point(chunks[0], chunks[1], chunks[2]), new Point(chunks[3], chunks[4], chunks[5]));
            primitive = (uint)((float)chunks[6]);
            skipIndex = (uint)((float)chunks[7]);
        }

        public byte[] Serialize()
        {
            return (new[]
                {
                    bbox.Min.Serialize(),
                    bbox.Max.Serialize(),
                    BitConverter.GetBytes(primitive),
                    BitConverter.GetBytes(skipIndex)
                }).SelectMany(x => x).ToArray();
        }

        public void Deserialize(byte[] data, int offset = 0)
        {
            var chunks = new[]
                {                    
                    BitConverter.ToSingle(data, offset),
                    BitConverter.ToSingle(data, offset + 4),
                    BitConverter.ToSingle(data, offset + 8),
                    BitConverter.ToSingle(data, offset + 12),
                    BitConverter.ToSingle(data, offset + 16),
                    BitConverter.ToSingle(data, offset + 20),
                    BitConverter.ToSingle(data, offset + 24),
                    BitConverter.ToSingle(data, offset + 28)
                };
            bbox = new AABBInfo(new Point(chunks[0], chunks[1], chunks[2]), new Point(chunks[3], chunks[4], chunks[5]));
            primitive = (uint)((float)chunks[6]);
            skipIndex = (uint)((float)chunks[7]);
        }
    }
}